//消息处理器
import common from './common.js'
import db from './db.js'
import apis from './apis.js'
import socket from './socket.js'
import JSEncrypt from './rsa.js'

export default {
	//消息ID
	msgId: 0,
	//消息事件
	msgEvent: {},
	//反馈事件
	fdEvent: {},
	//事件名称
	name: 'mh',
	//绑定
	bind() {
		this.handleFeedBack();
		this.handleAddFriend();
		this.handlePrivateMessage();
		this.handleGroupMessage();
		this.heartBeat();
		this.handleFriendApply();
		this.handleDeleteFriend();
		this.handleDeleteGroupMember();
		this.handleModifyGroupName();
		this.handleAddGroupMember();
		this.handleCreateGroup();
		this.handleSwitchGroupJoinType();
		this.handleJoinGroup();
		this.handleModifyUserInfo();
		this.handleOccupied();
		this.handleCancel();
		uni.onSocketMessage(data => {
			data = data.data;
			if (typeof data === 'string') {
				data = JSON.parse(data);
			}
			this.triggerMessageEvent(data);
		});
	},
	//解除绑定
	unBind() {
		this.unBindMessage({
			type: 'FeedBack',
			name: this.name
		});
		this.unBindMessage({
			type: 'Private',
			name: this.name
		});
		this.unBindMessage({
			type: 'Group',
			name: this.name
		});
		this.unBindMessage({
			type: 'AddFriend',
			name: this.name
		});
		this.unBindMessage({
			type: 'FriendApply',
			name: this.name
		});
		this.unBindMessage({
			type: 'DeleteFriend',
			name: this.name
		});
		this.unBindMessage({
			type: 'DeleteGroupMember',
			name: this.name
		});
		this.unBindMessage({
			type: 'ModifyGroupName',
			name: this.name
		});
		this.unBindMessage({
			type: 'SwitchGroupJoinType',
			name: this.name
		});
		this.unBindMessage({
			type: 'AddGroupMember',
			name: this.name
		});
		this.unBindMessage({
			type: 'CreateGroup',
			name: this.name
		});
		this.unBindMessage({
			type: 'JoinGroup',
			name: this.name
		});
		this.unBindMessage({
			type: 'ModifyUserInfo',
			name: this.name
		});
		this.unBindMessage({
			type: 'Occupied',
			name: this.name
		});
		this.unBindMessage({
			type: 'Cancel',
			name: this.name,
		});
	},
	//获取mId
	mId() {
		return ++this.msgId;
	},
	//发送消息
	sendMessage(data) {
		data.Code = data.Code || this.mId();
		data.SenderId = common.loginUser.Id;
		return new Promise((res, rej) => {
			uni.sendSocketMessage({
				data: JSON.stringify(data),
				success() {
					res(data.Code);
				},
				fail(err) {
					rej(err);
				}
			});
		});
	},
	//给服务器反馈
	sendFeedback(code) {
		this.sendMessage({
			Messagetype: 'FeedBack',
			Code: code
		});
	},
	//同步发送消息
	async sendMessageAsync(data) {
		data.Code = data.Code || this.mId();
		data.SenderId = data.SenderId || common.loginUser.Id;
		const [e, result] = await uni.sendSocketMessage({
			data: JSON.stringify(data)
		});
		//成功
		if (result && result.errMsg == 'sendSocketMessage:ok') {
			return new Promise((res, rej) => {
				let fail = false;
				let id = setTimeout(() => {
					fail = true;
					rej({
						handle: true
					});
					console.log('等待超时');
				}, 6000);
				this.bindFeedBack({
					code: data.Code,
					fn: d => {
						if (fail) {
							return;
						}
						clearTimeout(id);
						if (!d.Success) {
							if (data.no) {
								rej(d);
							} else {
								common.showToast(d.Data);
								rej({
									handle: true
								});
							}
							return;
						}
						res(d);
					}
				})
			});
		} else {
			return Promise.reject('发送失败');
		}
	},
	//反馈
	handleFeedBack() {
		this.bindMessage({
			type: 'FeedBack',
			name: this.name,
			fn: data => {
				if (this.fdEvent[data.Code]) {
					try {
						this.fdEvent[data.Code].call(this, data);
					} catch (e) {}
					delete this.fdEvent[data.Code];
				}
			}
		});
	},
	//绑定反馈
	bindFeedBack(data) {
		if (!this.fdEvent[data.code]) {
			this.fdEvent[data.code] = data.fn;
		}
	},
	//绑定消息
	bindMessage(data) {
		let event = (this.msgEvent[data.type] || (this.msgEvent[data.type] = []));
		if (!event.some(c => c.name == data.name)) {
			event.push(data);
		}
	},
	//解除绑定消息
	unBindMessage(data) {
		let event = (this.msgEvent[data.type] || (this.msgEvent[data.type] = []));
		let index = event.findIndex(c => c.name == data.name);
		if (index >= 0) {
			event.splice(index, 1);
		}
	},
	//触发消息事件
	triggerMessageEvent(data) {
		let event = this.msgEvent[data.Type];
		if (Array.isArray(event)) {
			event.forEach(item => {
				item.fn.call(this, data);
			});
		}
	},
	//处理内容
	handleContent(msg) {
		switch (msg.messageType) {
			case 'Image':
				return '[图片]';
			case 'Voice':
				return '[语音]';
			case 'File':
				return '[文件]';
			case 'Video':
				return '[视频]';
			default:
				return msg.content;
		}
	},
	//添加推送消息
	addPushMessage(msg) {
		if (!common.runBehind) {
			return;
		}
		try {
			let allMessages = plus.push.getAllMessage();
			let oldMsg = allMessages.find(c => c.payload.type == msg.type && c.payload.other == msg.other); //旧数据
			msg.msgcount = 1;
			if (oldMsg) {
				msg.msgcount = oldMsg.payload.msgcount + 1;
				if (isNaN(msg.msgcount)) {
					msg.msgcount = 1;
				}
				plus.push.remove(oldMsg); //如果旧数据存在则删除旧数据
			}
			if (msg.type == 1) {
				if (!msg.obj) {
					msg.obj = common.users.find(c => c.Id == msg.other) || {
						NickName: '您的好友',
						Avatar: '/static/logo.png',
						msgcount: 1
					};
				}
				plus.push.createMessage(`[${msg.msgcount}条]${msg.obj.NickName}:${this.handleContent(msg)}`, {
					type: msg.type,
					other: msg.other,
					msgcount: msg.msgcount
				}, {
					icon: common.getAvatar(msg.obj.Avatar),
					title: msg.obj.NickName
				});
			} else {
				const sender = msg.obj.members.find(c => c.Id == msg.senderId);
				plus.push.createMessage(`[${msg.msgcount}条]${sender.NickName}:${this.handleContent(msg)}`, {
					type: msg.type,
					other: msg.other,
					msgcount: msg.msgcount
				}, {
					icon: common.getAvatar(sender.Avatar),
					title: msg.obj.GroupName
				});
			}
		} catch (e) {
			console.log('添加推送失败', e);
		}
	},
	//移除推送
	removePush(data) {
		let pushMsgs = plus.push.getAllMessage();
		let pushMsg = pushMsgs.find(c => c.payload.other == data.other && c.payload.type == data.type);
		pushMsg && plus.push.remove(pushMsg);
	},
	//获取当前聊天的用户ID
	getCurrentUserId() {
		try {
			let page = getCurrentPages().pop();
			if (page.route.indexOf('/chat') > 0 && page.$vm.type == 1) {
				return (page.$vm.user || {}).Id;
			}
		} catch (e) {}
		return 0;
	},
	//获取当前群组ID
	getCurrentGroupId() {
		try {
			let page = getCurrentPages().pop();
			if (page.route.indexOf('/chat') > 0 && page.$vm.type == 2) {
				return (page.$vm.user || {}).Id;
			}
		} catch (e) {}
		return 0;
	},
	//处理私聊消息
	handlePrivateMessage() {
		this.bindMessage({
			type: 'Private',
			name: this.name,
			fn: async data => {
				//给服务器发反馈
				this.sendFeedback(data.Code);
				data = data.Data;
				let userId = this.getCurrentUserId();
				let msg = common.createNewMessage({
					serverId: data.Id,
					senderId: data.SenderId,
					time: common.parseDate(data.SendTime),
					messageType: data.MessageType,
					content: data.Message,
					other: data.SenderId,
					type: 1,
					property: data.Property,
					state: data.MessageType == 'Text' ? 1 : -1,
					read: data.MessageType != 'Voice' && !common.runBehind && userId == data.SenderId //如果前台运行并且是本人才算已读
				});
				try {
					await db.insertNewMessage(msg);
				} catch (e) {
					console.log('新数据插入失败', e);
				}
				common.execDelay(async () => {
					await this.setNewMessageByUser(msg);
					this.addPushMessage(msg);
				}, `setNewMessage${msg.type}_${msg.other}`);
			}
		});
	},
	//处理群聊消息
	handleGroupMessage() {
		this.bindMessage({
			type: 'Group',
			name: this.name,
			fn: async data => {
				//给服务器发反馈
				this.sendFeedback(data.Code);
				data = data.Data;
				let groupId = this.getCurrentGroupId();
				let msg = common.createNewMessage({
					serverId: data.Id,
					senderId: data.SenderId,
					time: common.parseDate(data.SendTime),
					messageType: data.MessageType,
					content: data.Message,
					other: data.GroupId,
					type: 2,
					property: data.Property,
					state: data.MessageType == 'Text' ? 1 : -1,
					read: data.MessageType != 'Voice' && !common.runBehind && groupId == data.GroupId //如果前台运行并且是本人才算已读
				});
				try {
					await db.insertNewMessage(msg);
				} catch (e) {
					console.log('新数据插入失败', e);
				}
				common.execDelay(async () => {
					await this.setNewMessageByUser(msg);
					this.addPushMessage(msg);
				}, `setNewMessage${msg.type}_${msg.other}`);
			}
		});
	},
	//处理添加好友
	handleAddFriend() {
		this.bindMessage({
			type: 'AddFriend',
			name: this.name,
			fn: async data => {
				if (!data.Success) {
					return;
				}
				this.sendFeedback(data.Code);
				data = data.Data;
				try {
					await apis.checkDownloadAvatar(data.Avatar);
					let msg = common.addNewFriend(data);
					await db.insertNewMessage(msg);
				} catch (e) {
					console.log('好友添加失败', e);
				}
			}
		});
	},
	//处理好友申请
	handleFriendApply() {
		this.bindMessage({
			type: 'FriendApply',
			name: this.name,
			fn: async data => {
				data = data.Data;
				try {
					await apis.checkDownloadAvatar(data.Avatar);
					data.ApplyDate = common.parseDate(data.ApplyDate);
					common.applyMsgs = data;
				} catch (e) {
					console.log('好友添加失败', e);
				}
			}
		});
	},
	//心跳
	heartBeat() {
		let failCount = 0;
		common.data.timeIds.push(
			setInterval(async () => {
				try {
					const {
						Data: {
							token
						}
					} = await this.sendMessageAsync({
						MessageType: 'ApplyToken'
					});
					failCount = 0;
					common.connected = true;
					common.token = token;
				} catch (e) {
					console.log('heart check failed,' + e);
					common.connected = false;
					console.log('心跳检测失败', e);
					//将所有同步都重置
					common.chatMessageAsync();
					try {
						await socket.initSocket(); //重新连接
						console.log('重连成功');
						let page = getCurrentPages().pop();
					} catch (e) {
						console.log('重连失败', e);
					}
					if (++failCount >= 10) {
						uni.showAlert({
							content: '已尝试重新连接10次仍未解决，可能服务未启动，需要您尝试重新登录'
						});
						common.clearAllData();
						uni.reLaunch({
							url: '/pages/login/login'
						});
					}
				}
			}, 10000)
		);
	},
	//处理删除好友消息
	handleDeleteFriend() {
		this.bindMessage({
			type: 'DeleteFriend',
			name: this.name,
			fn: async data => {
				data = data.Data; //用户ID
				//从好友中删除
				common.friends = data;
				//删除好友消息
				const f = {
					other: data,
					type: 1
				};
				db.deleteMessageByOther(f);
				//移除最新消息
				common.removeNewMessage(f);
				//如果是聊天页则判断是否为删除的用户
				if (this.getCurrentUserId() == data) {
					uni.navigateBack();
				}
				//如果是好友信息
				else {
					const pages = getCurrentPages();
					const page = pages.pop();
					if (page.route.indexOf('friendInfo') > 0) {
						//判断显示的好友信息是否为删除的用户
						if ((page.$vm.user || {}).Id == data) {
							let delta = 1;
							if (pages.pop().route.indexOf('/chat') > 0) {
								delta++; //再往前一个页面时聊天页则需返回两层
							}
							uni.navigateBack({
								delta
							});
						}
					}
				}
			}
		});
	},
	//处理创建群组消息
	handleCreateGroup() {
		this.bindMessage({
			type: 'CreateGroup',
			name: this.name,
			fn: async data => {
				this.sendFeedback(data.Code);
				data = data.Data;
				try {
					await apis.BatchCheckDownloadAvatars(data.members.map(c => c.Avatar));
					common.addGroupMember(data.group, data.members);
					let msg = common.addNewGroup(data.group, data.msg);
					db.insertNewMessage(msg);
				} catch (e) {
					console.log('创建群组消息处理失败', e);
				}
			}
		});
	},
	//处理删除群组成员消息
	handleDeleteGroupMember() {
		this.bindMessage({
			type: 'DeleteGroupMember',
			name: this.name,
			fn: async data => {
				this.sendFeedback(data.Code);
				data = data.Data;
				//如果删除的是当前用户
				if (data.deleteSelf) {
					//把群组和消息都删除
					common.deleteGroup(data.gId);
					//如果是聊天页则判断是否为删除的用户
					if (this.getCurrentGroupId() == data.gId) {
						uni.navigateBack();
					}
					//如果是群组信息则判断是否为删除的用户
					else {
						//开始判断是否要返回页面
						let pages = getCurrentPages();
						let page = pages.pop();
						if (page.route.indexOf('/groupInfo') > 0) {
							let gId = (page.$vm.group || {}).Id;
							if (gId == data.gId) {
								uni.navigateBack({
									delta: 2
								});
							}
						}
					}
					//删掉数据库中的数据
					db.deleteMessageByOther({
						other: data.gId,
						type: 2
					});
				} else {
					//如果不是本人则直接从群组中移除掉相应的用户
					common.deleteGroupMembers(data.gId, data.userIds);
					common.setGroupTitle(data.gId);
					let msg = common.createNewMessage({
						type: 2,
						content: data.msg,
						other: data.gId,
						messageType: 'System',
						read: true,
					});
					common.newMessage = msg;
					common.addGroupMsg(msg);
					db.insertNewMessage(msg);
				}
			}
		});
	},
	//处理修改群组名称消息
	handleModifyGroupName() {
		this.bindMessage({
			type: 'ModifyGroupName',
			name: this.name,
			fn: async data => {
				data = data.Data;
				let group = common.groups.find(c => c.Id == data.gId);
				if (group) {
					group.GroupName = data.name;
					let msg = common.newMessage.find(c => c.other == data.gId && c.type == 2);
					msg && (msg.groupname = data.name);
				}
			}
		});
	},
	//处理修改群组名称消息
	handleSwitchGroupJoinType() {
		this.bindMessage({
			type: 'SwitchGroupJoinType',
			name: this.name,
			fn: async data => {
				data = data.Data;
				let group = common.groups.find(c => c.Id == data.gId);
				if (group) {
					group.JoinType = data.type;
				}
			}
		});
	},
	//处理添加群组成员
	handleAddGroupMember() {
		this.bindMessage({
			type: 'AddGroupMember',
			name: this.name,
			fn: async data => {
				this.sendFeedback(data.Code);
				data = data.Data;
				try {
					await apis.BatchCheckDownloadAvatars(data.members.map(c => c.Avatar));
					//添加群组成员
					common.addGroupMember(data.gId, data.members);
					common.setGroupTitle(data.gId);
					let msg = common.createNewMessage({
						content: data.msg,
						other: data.gId,
						type: 2,
						messageType: 'System',
						read: true
					});
					common.newMessage = msg;
					common.addGroupMsg(msg);
					db.insertNewMessage(msg);
				} catch (e) {
					console.log('新数据插入失败', e);
				}
			}
		});
	},
	//处理加入群组
	handleJoinGroup() {
		this.bindMessage({
			type: 'JoinGroup',
			name: this.name,
			fn: async data => {
				this.sendFeedback(data.Code);
				data = data.Data;
				try {
					await apis.BatchCheckDownloadAvatars(data.members.map(c => c.Avatar));
					common.addGroupMember(data.group, data.members);
					let msg = common.addNewGroup(data.group, data.msg);
					db.insertNewMessage(msg);
				} catch (e) {
					console.log('创建群组消息处理失败', e);
				}
			}
		});
	},
	//处理修改用户信息消息
	handleModifyUserInfo() {
		this.bindMessage({
			type: 'ModifyUserInfo',
			name: this.name,
			fn: async data => {
				data = data.Data;
				//如果是头像则先下载
				if (data.field == 'Avatar') {
					try {
						await apis.checkDownloadAvatar(data.value);
						common.setGroupAvatarsByUserId(data.userId);
					} catch (e) {
						console.log('好友更换头像，但是下载失败', e, data);
						return; //下载失败则不更换
					}
				}
				let friend = common.friends.find(c => c.Id == data.userId);
				friend && (friend[data.field] = data.value);
			}
		});
	},
	//处理撤回消息
	handleCancel() {
		this.bindMessage({
			type: 'Cancel',
			name: this.name,
			fn: async data => {
				//给服务器发反馈
				this.sendFeedback(data.Code);
				data = data.Data;
				try {
					let msg = await db.getMessageByServerId(data.id, data.type);
					msg = msg.shift();
					msg.msg = data.msg;
					msg.time = common.serverTime;
					this.cancelMsg(msg);
				} catch (e) {
					console.log('撤回失败', e);
				}
			}
		});
	},
	//撤回消息
	async cancelMsg(msg) {
		//非文本消息并且已下载文件的则删除
		if (msg.messageType != 'Text' && msg.state == 1) {
			uni.removeSavedFile({
				filePath: msg.content
			});
		}
		db.deleteMessageByServerId(msg.id);
		const userId = msg.type == 1 ? this.getCurrentUserId() : this.getCurrentGroupId();
		msg = common.createNewMessage({
			type: msg.type,
			content: msg.msg,
			other: msg.other,
			time: msg.time,
			messageType: 'System',
			read: userId == msg.other //如果前台运行并且是本人才算已读
		});
		common.newMessage = msg;
		try {
			await db.insertNewMessage(msg);
		} catch (e) {
			console.log('插入失败', e);
		}
	},
	//处理占线
	handleOccupied() {
		this.bindMessage({
			type: 'Occupied',
			name: this.name,
			fn: () => {
				uni.showAlert({
					content: '您的账号已在其他地方登录，如已被盗请及时修改密码'
				});
				common.clearAllData();
				uni.reLaunch({
					url: '/pages/login/login'
				});
			}
		});
	},
	//设置未数数
	async setUnreadCount(other, type) {
		let data = await db.getUnreadCount({
			other,
			type
		});
		data = data.shift();
		common.unreadCount = {
			other,
			type,
			msgcount: data.count
		};
	},
	//根据用户设置最新消息
	async setNewMessageByUser(data) {
		let msg = await db.getNewestMessageByUser(data);
		let newMsg = common.createNewMessage(msg);
		newMsg.msgcount = 0;
		common.newMessage = newMsg;
		common.unreadCount = msg;
		return msg;
	},
	//删除群组成员
	deleteGroupMember(groupId, userIds) {
		return this.sendMessageAsync({
			MessageType: 'DeleteGroupMember',
			ReceiverId: groupId,
			Content: userIds
		});
	},
	//修改群组名称
	modifyGroupName(groupId, name) {
		return this.sendMessageAsync({
			MessageType: 'ModifyGroupName',
			ReceiverId: groupId,
			Content: name
		});
	},
	//切换群组加入方式
	switchGroupJoinType(groupId, type) {
		return this.sendMessageAsync({
			MessageType: 'SwitchGroupJoinType',
			ReceiverId: groupId,
			Content: type
		});
	},
	//修改昵称
	modifyNickname(nickname) {
		return this.sendMessageAsync({
			MessageType: 'ModifyNickname',
			Content: nickname
		});
	},
	//切换用户添加方式
	switchUserAddType(type) {
		return this.sendMessageAsync({
			MessageType: 'SwitchUserAddType',
			ReceiverId: type
		});
	},
	//更改头像
	changeAvatar(avatar) {
		return this.sendMessage({
			MessageType: 'ChangeAvatar',
			Content: avatar
		});
	},
	//删除群组
	deleteGroup(groupId) {
		return this.sendMessageAsync({
			MessageType: 'DeleteGroup',
			ReceiverId: groupId
		});
	},
	//添加群组成员
	addGroupMember(groupId, userIds, message) {
		return this.sendMessageAsync({
			MessageType: 'AddGroupMember',
			ReceiverId: groupId,
			Property: userIds,
			Content: message
		});
	},
	//加入群组
	joinGroup(groupId, message) {
		return this.sendMessageAsync({
			MessageType: 'JoinGroup',
			ReceiverId: groupId,
			Content: message
		});
	},
	//创建群组
	createGroup(userIds) {
		return this.sendMessageAsync({
			MessageType: 'CreateGroup',
			Content: userIds
		});
	},
	//根据用户ID获取用户
	getUserById(userId) {
		return this.sendMessageAsync({
			MessageType: 'GetUser',
			ReceiverId: userId
		});
	},
	//为了入群获取群组信息
	getGroupForJoin(groupId) {
		return this.sendMessageAsync({
			MessageType: 'GetGroupForJoin',
			ReceiverId: groupId
		});
	},
	//根据ID获取用户
	getUserByIds(ids) {
		return this.sendMessageAsync({
			MessageType: 'GetUserByIds',
			Content: ids
		});
	},
	//处理请求
	handleApply(id, agree) {
		return this.sendMessageAsync({
			MessageType: 'HandleApply',
			ReceiverId: id,
			Content: agree
		});
	},
	//获取邮箱验证码
	emailCaptcha(email) {
		return this.sendMessageAsync({
			MessageType: 'EmailCaptcha',
			Content: email
		});
	},
	//设置邮箱
	setEmail(captcha) {
		return this.sendMessageAsync({
			MessageType: 'SetEmail',
			Content: captcha
		});
	},
	//获取手机验证码
	phoneCaptcha(phone) {
		return this.sendMessageAsync({
			MessageType: 'PhoneCaptcha',
			Content: phone
		});
	},
	//设置手机
	setPhone(captcha) {
		return this.sendMessageAsync({
			MessageType: 'SetPhone',
			Content: captcha
		});
	},
	//发送重置密码验证码
	resetPasswordCaptcha(type) {
		return this.sendMessageAsync({
			MessageType: 'ResetPasswordCaptcha',
			ReceiverId: type
		});
	},
	//验证重置密码验证码
	validResetPasswordCaptcha(type, captcha) {
		return this.sendMessageAsync({
			MessageType: 'ValidResetPasswordCaptcha',
			ReceiverId: type,
			Content: captcha
		});
	},
	//转发消息
	transferMsg(receiverId, type, id) {
		return this.sendMessageAsync({
			MessageType: 'Transfer',
			Content: id,
			ReceiverId: receiverId,
			Property: type == 1 ? 'p' : 'g'
		});
	},
	//发送私聊和群聊消息
	sendPGMessage(data) {
		return this.sendMessageAsync({
			MessageType: data.type == 1 ? 'Private' : 'Group',
			ChatMessageType: data.messageType,
			ReceiverId: data.other,
			Content: data.content,
			Property: JSON.stringify(data.property || '')
		});
	},
	//修改密码
	modifyPassword(oldPassword, newPassword) {
		const encrypt = new JSEncrypt();
		encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + common.publicKey + '-----END PUBLIC KEY-----');
		newPassword = encrypt.encrypt(newPassword);
		oldPassword = encrypt.encrypt(oldPassword);
		return this.sendMessageAsync({
			MessageType: 'ModifyPassword',
			Property: oldPassword,
			Content: newPassword
		});
	},
	//撤回消息
	cancel(id, type) {
		return this.sendMessageAsync({
			MessageType: 'Cancel',
			ReceiverId: id,
			Property: type == 1 ? 'p' : 'g'
		});
	},
	//获取待办指令
	getTodoCommand() {
		return this.sendMessageAsync({
			MessageType: 'GetTodoCommand'
		});
	},
	//获取未读总数
	getUnreadCount(no) {
		return this.sendMessageAsync({
			MessageType: 'UnreadCount',
			no
		});
	}
}
